package tagdb.algorithm.graph;

import tagdb.fragmentation.SpectrumPeak;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * General  graph class consisting of peaks as nodes and edges.
 * @author Thilo Muth
 *
 */
public class Graph {

    // The vertices/nodes
    private Map<Double, SpectrumPeak> peaks;

    // The egdes: connections between the peaks aka. their mass differences.
    private List<Edge> edges;

    /**
     * The start edges are all connection starting from the (0.0, 1.0) peak.
     */
    private List<Edge> startEdges;

    /**
     * Constructing the graph with nodes and egdes.
     * @param peaks Spectrum peaks.
     */
    public Graph(List<SpectrumPeak> peaks) {
        fillPeakMap(peaks);
        init();
    }

    /**
     * Fills the peak map.
     * @param peaks List of spectrum peaks.
     */
    private void fillPeakMap(List<SpectrumPeak> peaks) {
        this.peaks = new HashMap<Double, SpectrumPeak>();
        this.peaks.put(0.0, new SpectrumPeak(0.0, 1.0));
        for(SpectrumPeak p : peaks) {
            this.peaks.put(p.getMZ(), p);
        }
    }

    /**
     * Get the start edges.
     * @return List of start edges.
     */
    public List<Edge> getStartEdges() {
        return startEdges;
    }

    /**
     * Returns the edges for a specific spectrum peak.
     * @param peak SpectrumPeak
     * @return List of edges for a specific spectrum peak.
     */
    public List<Edge> getEdgesForPeak(SpectrumPeak peak){
        return this.peaks.get(peak.getMZ()).getEdges();
    }

    /**
     * Initialize the graph.
     */
    private void init() {
        edges = new ArrayList<Edge>();
        for(SpectrumPeak p1 : peaks.values()) {
            for(SpectrumPeak p2 : peaks.values()) {
                if(!p1.equals(p2)){
                    Edge e = new Edge(p1, p2);
                    p1.addEdge(e);
                    p2.addEdge(e);
                    edges.add(e);
                }
            }
        }
    }

    /**
     * Returns the peaks in the graph.
     * @return the peaks in the graph
     */
    public List<SpectrumPeak> getPeaks() {
        return new ArrayList<SpectrumPeak>(peaks.values());
    }

    /**
     * Returns the edges in the graph.
     * @return the edges in the graph
     */
    public List<Edge> getEdges(){
        return edges;
    }

    /**
     * Adds an edge to the graph.
     * @param e
     */
    public void addEdge(Edge e){
        edges.add(e);
    }
}


